#include "ImgDivision.h"

ImgDivision::ImgDivision(QImage *img)
{
    m_Img = img;
    //基于阈值的初始化
    //*************
    //初始化灰度级数组
    for (int i = 0; i<256; i++) {
        m_GrayLevel[i] = 0;
    }
    //获取灰度级
    getGrayLevel();
    //计算类间方差 得到最优阈值
    double g = 0;
    for (int i = 0; i<256; i++) {
        if(g < getInterclassVariance(i)){
            g = getInterclassVariance(i);
            m_BestThreshold = i;
        }
    }
    //qDebug()<<g<<"   "<<m_BestThreshold;
    //基于并行边界分割算子初始化
    //*************
    //初始化各算子大小
    //Roborts算子，
    m_Grad_Roberts.resize(m_Img->height()-1);
    for (int i = 0; i < m_Grad_Roberts.size(); i++) {
        m_Grad_Roberts[i].resize(m_Img->width()-1);
    }
    //Prewitt算子
    m_Grad_Prewitt.resize(m_Img->height()-2);
    for (int i = 0; i< m_Grad_Prewitt.size(); i++) {
        m_Grad_Prewitt[i].resize(m_Img->width()-2);
    }
    //Sobel算子
    m_Grad_Sobel.resize(m_Img->height()-2);
    for (int i = 0; i< m_Grad_Sobel.size(); i++) {
        m_Grad_Sobel[i].resize(m_Img->width()-2);
    }
    //m_Grad_Laplacian4 算子
    m_Grad_Laplacian4.resize(m_Img->height()-2);
    for (int i = 0; i< m_Grad_Laplacian4.size(); i++) {
        m_Grad_Laplacian4[i].resize(m_Img->width()-2);
    }
    //m_Grad_Laplacian8
    m_Grad_Laplacian8.resize(m_Img->height()-2);
    for (int i = 0; i< m_Grad_Laplacian8.size(); i++) {
        m_Grad_Laplacian8[i].resize(m_Img->width()-2);
    }
    //获取各算子的值
    getGradientValue();
    //基于区域生长的初始化
    //**************
    //获取区域增长后的结果
    //getRegionGrowResult(3.0);//初始化阈值为3.0
    //qDebug()<<"region grow runs success::"<<m_RegionGet.size();
    //qDebug()<<m_Img->height() * m_Img->width()/2;
}

QImage* ImgDivision::byThreshold(int threshold)
{
    QImage *newImg = new QImage(m_Img->width(), m_Img->height(), QImage::Format_ARGB32);
    for(int y = 0; y<m_Img->height(); y++)
    {
        QRgb * line = (QRgb *)m_Img->scanLine(y);
        for(int x = 0; x<m_Img->width(); x++)
        {
            int average = (qRed(line[x]) + qGreen(line[x]) + qBlue(line[x]))/3;
            if(average < threshold){
                newImg->setPixel(x,y, qRgb(255, 255, 255));
            }else {
                newImg->setPixel(x,y, qRgb(0, 0, 0));
            }
        }
    }
    return newImg;
}

QImage* ImgDivision::byThreshold_Otsu()
{
    return byThreshold(m_BestThreshold);
}

QImage* ImgDivision::byParallelEdge(double threshold, QString method)
{
    if(method == "Roberts")
    {
        QImage *newImg = new QImage(m_Img->width()-1, m_Img->height()-1, QImage::Format_ARGB32);
        for(int y = 0; y<m_Img->height()-1; y++)
        {
            for(int x = 0; x<m_Img->width()-1; x++)
            {
                if(m_Grad_Roberts[y][x]<threshold){
                    newImg->setPixel(x,y, qRgb(255, 255, 255));
                }else {
                    newImg->setPixel(x,y, qRgb(0, 0, 0));
                }
            }
        }
        return newImg;
    }else
    {
        QImage *newImg = new QImage(m_Img->width()-2, m_Img->height()-2, QImage::Format_ARGB32);
        for(int y = 0; y<m_Img->height()-2; y++)
        {
            for(int x = 0; x<m_Img->width()-2; x++)
            {
                if(method == "Prewitt"){
                    if(m_Grad_Prewitt[y][x]<threshold){
                        newImg->setPixel(x,y, qRgb(255, 255, 255));
                    }else {
                        newImg->setPixel(x,y, qRgb(0, 0, 0));
                    }
                }
                if(method == "Sobel"){
                    if(m_Grad_Sobel[y][x]<threshold){
                        newImg->setPixel(x,y, qRgb(255, 255, 255));
                    }else {
                        newImg->setPixel(x,y, qRgb(0, 0, 0));
                    }
                }
                if(method == "Laplacian4"){
                    if(m_Grad_Laplacian4[y][x]<threshold){
                        newImg->setPixel(x,y, qRgb(255, 255, 255));
                    }else {
                        newImg->setPixel(x,y, qRgb(0, 0, 0));
                    }
                }
                if(method == "Laplacian8"){
                    if(m_Grad_Laplacian8[y][x]<threshold){
                        newImg->setPixel(x,y, qRgb(255, 255, 255));
                    }else {
                        newImg->setPixel(x,y, qRgb(0, 0, 0));
                    }
                }
            }
        }
        return newImg;
    }
}

QImage* ImgDivision::byRegionGrow(vector<int> seeds, double threshold, int fourOrEight)
{
    m_Seeds[0] = seeds[0];
    m_Seeds[1] = seeds[1];
    //m_Seeds[2] = 0;//状态弃用
    //清空区域
    while(!m_RegionGet.empty())
    {
        m_RegionGet.pop();
    }
    //获得新区域
    getRegionGrowResult(threshold, fourOrEight);
    //显示
    QImage *newImg = new QImage(m_Img->width(), m_Img->height(), QImage::Format_ARGB32);
    //背景板
    for(int y = 0; y<m_Img->height(); y++)
    {
        QRgb * line = (QRgb *)m_Img->scanLine(y);
        for(int x = 0; x<m_Img->width(); x++)
        {
            newImg->setPixel(x,y, qRgb(0, 255, 0));
        }
    }
    //生成的区域
    while(!m_RegionGet.empty()){
        int x = m_RegionGet.front()[0];
        int y = m_RegionGet.front()[1];
        m_RegionGet.pop();
        newImg->setPixel(x, y, m_Img->pixel(x,y));
    }
    return newImg;
}

QImage* ImgDivision::bySLIC()
{
    vector<double> val1 =  getImgComplexity();//计算图像复杂度、信息熵
    vector<double> val2 = getGLCMfeatures(0);//计算共生矩阵特征值
    //图像复杂度
    qDebug()<<val1[1]<<" "<<val2[0]<<" "<<val2[1]<<" "<<val2[2];
    double Tk = val1[1]+val2[0]-val2[1]-val2[2];
    qDebug()<<"complexity:"<<Tk;

    //计算超像素的个数
    int K =  int((m_Img->width() + m_Img->height()) / Tk);
    //说明！！！！！！
    //K计算有问题，Tk计算结果很大，后续再重新顺一下，大概率在共生矩阵特征值计算中有问题
    //设置K为固定值
    K = 36;
    //!!!!!!

    //每个超像素大小  +1为了不在最后 -宽高不在边上
    int pixelSize = int((m_Img->width() * m_Img->height() - m_Img->width() *2 -m_Img->height()*2) / (K+1));
    //步长 感觉有问题 能直接开根？？
    int S = int(sqrt(pixelSize));
    qDebug()<<"stride:"<<S;
    //初始化聚类中心种子点
    vector<vector<int>> seeds;
    seeds.resize(K);
    for (int i = 0; i<seeds.size(); i++) {
        seeds[i].resize(3);
    }
    int cycle = 0;//到达超像素大小后 存储该点 重置
    int num = 0;//超像素序号
    for (int y = 1; y<m_Img->height()-1; y++) {
        for (int x = 1; x<m_Img->width()-1;x++) {
            cycle ++ ;
            if(cycle == pixelSize)
            {
                cycle = 0;
                num++;
                seeds[num-1] = {y, x, num};
            }
            if(num == K) break;
        }
        if(num == K) break;
    }
    qDebug()<<num<<" "<<K;
    //计算初始种子点邻域内，修改种子点到梯度最小处
    vector<vector<int>> neighborhood = {{0,-1},{0,1},{-1,0},{1,0},{-1,-1},{-1,1},{1,-1},{1,1}};
    for (int i = 0; i<K; i++)
    {
        int y = seeds[i][0];
        int x = seeds[i][1];
        //初始种子点处中心梯度
        double gradX = abs((getPixelAvg(x+1, y) - getPixelAvg(x-1, y)) / 2.0);
        double gradY = abs((getPixelAvg(x, y+1) - getPixelAvg(x, y-1)) / 2.0);
        double centerGrad = sqrt(gradX*gradX + gradY*gradY);
        if(centerGrad == 0.0) continue;

        //其余邻域的中心梯度
        for (int j = 0; j<8; j++)
        {
            int thisX = x + neighborhood[j][0];
            int thisY = y + neighborhood[j][1];
            //在边界返回 下一次循环
            if((thisX <= 0)||(thisX >= m_Img->width()-1)||(thisY<=0)||(thisY>=m_Img->height()-1)) continue;
            //该点的中心梯度
            double gradThisX = abs((getPixelAvg(thisX+1, thisY) - getPixelAvg(thisX-1, thisY)) / 2.0);
            double gradThisY = abs((getPixelAvg(thisX, thisY+1) - getPixelAvg(thisX, thisY-1)) / 2.0);
            double thisGrad = sqrt(gradThisX*gradThisX + gradThisY*gradThisY);

            if(thisGrad < centerGrad)
            {
                centerGrad = thisGrad;
                seeds[i][0] = thisY;
                seeds[i][1] = thisX;
            }
        }
    }
    qDebug()<<"seeds complete.";
    //设置种子模板 用于判断处于哪个种子中心
    vector<vector<int>> seedsTemplate;
    seedsTemplate.resize(m_Img->height());
    for (int i = 0; i < seedsTemplate.size(); i++) {
        seedsTemplate[i].resize(m_Img->width());
    }
    for (int i = 0; i<seeds.size(); i++)
    {
        seedsTemplate[seeds[i][0]][seeds[i][1]] = seeds[i][2];
    }
    qDebug()<<"seedsTemplate complete.";
    //计算图像的lab
    vector<vector<vector<double>>> lab = getLab();
    qDebug()<<"lab compute complete.";

    //初始化分割结果的 大小
    vector<vector<int>> divRes;
    divRes.resize(m_Img->height());
    for (int i = 0; i < divRes.size(); i++) {
        divRes[i].resize(m_Img->width());
    }
    //计算每个像素的中心
    vector<vector<int>> divDis = divRes;//存储距离
    for(int y = 0; y<m_Img->height(); y++)
    {
        for(int x = 0; x<m_Img->width(); x++)
        {
            divDis[y][x] = 12000.0;
        }
    }
    qDebug()<<"divRes and divDis complete. run begin";
    /*
    //对种子的2S*2S区域遍历
    for (int i = 0; i < seeds.size(); i++) {
        int seedX = seeds[i][1];
        int seedY = seeds[i][0];
        //2S*2S区域
        int xmin = seedX - S;
        if(xmin<0) xmin = 0;
        int xmax = seedX + S + 1;
        if(xmax>m_Img->width()) xmax = m_Img->width();
        int ymin = seedY - S;
        if(ymin<0) ymin = 0;
        int ymax = seedY + S + 1;
        if(ymax>m_Img->height()) ymax = m_Img->height();
        //qDebug()<<i<<"number:"<<seedY<<" "<<seedX<<" "<<xmin<<" "<<xmax<<"::"<<ymin<<" "<<ymax;
        for (int yy = ymin; yy<ymax; yy++) {
            for (int xx = xmin; xx<xmax; xx++) {
                double thisDis = getDistance(QPoint(seedX,seedY),QPoint(xx,yy), lab, K, 4);
                if(divDis[yy][xx] > thisDis)
                {
                    divDis[yy][xx] = thisDis;
                    divRes[yy][xx] = seedsTemplate[seedY][seedX];
                }
            }
        }
        qDebug()<<"seeds all:"<<K<<"_"<<"number:"<<i+1<<":complete.";
    }
    */
    //计算每个像素所处的聚类中心
    for(int y = 0; y<m_Img->height(); y++)
    {
        qDebug()<<"ALL height:"<<m_Img->height()<<"_this:"<<y+1;
        for(int x = 0; x<m_Img->width(); x++)
        {
            double minDis = 120.0;//初始化最小距离
            //2S*2S区域
            int xmin = x - S;
            if(xmin<0) xmin = 0;
            int xmax = x + S + 1;
            if(xmax>m_Img->width()) xmax = m_Img->width();
            int ymin = y - S;
            if(ymin<0) ymin = 0;
            int ymax = y + S + 1;
            if(ymax>m_Img->height()) ymax = m_Img->height();
            //循环判断处于哪个聚类中心
            for (int yy = ymin; yy<ymax; yy++) {
                for (int xx = xmin; xx<xmax; xx++) {
                    if(seedsTemplate[yy][xx] > 0)
                    {   //该位置是聚类中心
                        //qDebug()<<yy<<" "<<xx<<" "<<seedsTemplate[yy][xx];
                        double thisDis = getDistance(QPoint(x,y),QPoint(xx,yy), lab, K, 4);
                        //更新最小距离
                        if(thisDis<minDis)
                        {
                            minDis = thisDis;
                            //设置该处像素为 聚类中心
                            divRes[y][x] = seedsTemplate[yy][xx];
                        }
                    }
                }
            }
        }
    }
    QImage *newImg = new QImage(m_Img->width(), m_Img->height(), QImage::Format_ARGB32);
    //背景板
    for(int y = 0; y<m_Img->height()-1; y++)
    {
        for(int x = 0; x<m_Img->width()-1; x++)
        {
            if((divRes[y][x+1] != divRes[y][x])||(divRes[y+1][x] != divRes[y][x]))
            {
                newImg->setPixel(x,y, qRgb(0, 0, 255));
            }
            else {
                newImg->setPixel(x,y, m_Img->pixel(x, y));
            }
        }
    }
    return newImg;
}

double  ImgDivision::getInterclassVariance(int first_threshold){
    //w0	分开后前景像素点数占图像的比例
    double frontNums = 0.0;
    double frontGraySum = 0;
    for (int i = 0; i < first_threshold; i++) {
        frontNums = frontNums + m_GrayLevel[i];
        frontGraySum = frontGraySum + m_GrayLevel[i] * i;
    }
    double w0 = frontNums / (m_Img->width() * m_Img->height());
    //u0	分开后前景像素点的平均灰度
    double u0 = frontGraySum / frontNums;
    //w1	分开后背景像素点数占图像的比例
    double backNums = 0.0;
    double backGraySum = 0;
    for (int i = first_threshold; i < 256; i++) {
        backNums = backNums + m_GrayLevel[i];
        backGraySum = backGraySum + m_GrayLevel[i] * i;
    }
    double w1 = backNums / (m_Img->width() * m_Img->height());
    // u1	分开后背景像素点的平均灰度
    double u1 = backGraySum / backNums;
    return w0*w1*(u0-u1)*(u0-u1);
}

void ImgDivision::getGrayLevel()
{
    for(int y = 0; y<m_Img->height(); y++)
    {
        QRgb * line = (QRgb *)m_Img->scanLine(y);
        for(int x = 0; x<m_Img->width(); x++)
        {
            int average = (qRed(line[x]) + qGreen(line[x]) + qBlue(line[x]))/3;
            m_GrayLevel[average] = m_GrayLevel[average] + 1;
        }
    }
}

void ImgDivision::getGradientValue()
{
    //Roberts 算子
    for(int y = 0; y<m_Img->height()-1; y++)
    {
        QRgb * line1 = (QRgb *)m_Img->scanLine(y);
        QRgb * line2 = (QRgb *)m_Img->scanLine(y+1);
        for(int x = 0; x<m_Img->width()-1; x++)
        {
            double average11 = (qRed(line1[x]) + qGreen(line1[x]) + qBlue(line1[x]))/3.0/255.0;
            double average12 = (qRed(line1[x+1]) + qGreen(line1[x+1]) + qBlue(line1[x+1]))/3.0/255.0;

            double average21 = (qRed(line2[x]) + qGreen(line2[x]) + qBlue(line2[x]))/3.0/255.0;
            double average22 = (qRed(line2[x+1]) + qGreen(line2[x+1]) + qBlue(line2[x+1]))/3.0/255.0;

            m_Grad_Roberts[y][x] = pow((pow((average22 - average11),2)  + pow((average21- average12),2)),0.5);
        }
    }
    //Prewitt Sobel 算子
    for(int y = 1; y<m_Img->height()-1; y++)
    {
        QRgb * line0 = (QRgb *)m_Img->scanLine(y-1);
        QRgb * line1 = (QRgb *)m_Img->scanLine(y);
        QRgb * line2 = (QRgb *)m_Img->scanLine(y+1);
        for(int x = 1; x<m_Img->width()-1; x++)
        {
            double average11 = (qRed(line0[x-1]) + qGreen(line0[x-1]) + qBlue(line0[x-1]))/3.0/255.0;
            double average12 = (qRed(line0[x]) + qGreen(line0[x]) + qBlue(line0[x]))/3.0/255.0;
            double average13 = (qRed(line0[x+1]) + qGreen(line0[x+1]) + qBlue(line0[x+1]))/3.0/255.0;

            double average21 = (qRed(line1[x-1]) + qGreen(line1[x-1]) + qBlue(line1[x-1]))/3.0/255.0;
            double average22 = (qRed(line1[x]) + qGreen(line1[x]) + qBlue(line1[x]))/3.0/255.0;
            double average23 = (qRed(line1[x+1]) + qGreen(line1[x+1]) + qBlue(line1[x+1]))/3.0/255.0;

            double average31 = (qRed(line2[x-1]) + qGreen(line2[x-1]) + qBlue(line2[x-1]))/3.0/255.0;
            double average32 = (qRed(line2[x]) + qGreen(line2[x]) + qBlue(line2[x]))/3.0/255.0;
            double average33 = (qRed(line2[x+1]) + qGreen(line2[x+1]) + qBlue(line2[x+1]))/3.0/255.0;

            //Prewitt算子
            double gx_Prewitt = (average31 + average32 + average33) - (average11 + average12 + average13);
            double gy_Prewitt = (average13 + average23 + average33) - (average11 + average21 + average31);
            m_Grad_Prewitt[y-1][x-1] = pow((pow(gx_Prewitt,2)  + pow(gy_Prewitt, 2)),0.5);
            //Sobel算子
            double gx_Sobel = (average31 + 2*average32 + average33) - (average11 + 2*average12 + average13);
            double gy_Sobel = (average13 + 2*average23 + average33) - (average11 + 2*average21 + average31);
            m_Grad_Sobel[y-1][x-1] = pow((pow(gx_Sobel,2)  + pow(gy_Sobel, 2)),0.5);
            //m_Grad_Laplacian4
            m_Grad_Laplacian4[y-1][x-1] = abs(4*average22 - (average12 + average21 + average23 + average32));
            //m_Grad_Laplacian8
            m_Grad_Laplacian8[y-1][x-1] = abs(8*average22 - (average11 + average12 + average13
                                                             + average21 + average23
                                                             + average31 + average32 + average33));
        }
    }
}

double ImgDivision::getPixelAvg(int x, int y){
    if((x<0)||(x>m_Img->width()-1)||(y<0)||(y>m_Img->height()-1)){ return -1.0;}
    QRgb pix = m_Img->pixel(x, y);
    return (qRed(pix) + qGreen(pix) + qBlue(pix))/3.0;
}

void ImgDivision::getRegionGrowResult(double threshold, int fourOrEight)
{
    m_RegionGet.push({m_Seeds[0], m_Seeds[1]});
    //模板 存储遍历到的像素状态 初始为0 默认都未选中
    vector<vector<int>> pixelState;
    pixelState.resize(m_Img->height());
    for (int i = 0; i < pixelState.size(); i++) {
        pixelState[i].resize(m_Img->width());
    }
    for (int i = 0; i<m_Img->height(); i++) {
        for (int j = 0; j<m_Img->width(); j++) {
            pixelState[i][j] = 0;
        }
    }
    //设置种子点处为1
    pixelState[m_Seeds[0]][m_Seeds[1]] = 1;

    //计算下一轮的种子
    queue<vector<int>> eachRound;//每一循环存储的新种子
    queue<vector<int>> nextRound;//下一循环存储的新种子
    eachRound.push(m_Seeds);
    int i = 0;//循环次数 设置为1200次  实际达不到 到eachRound为空就停止了
    double center_avg = getPixelAvg(m_Seeds[0], m_Seeds[1]);//中心种子的灰度(全部种子的灰度均值)
    int seedsNums = 0;//全部的区域种子数 (不包括初始的种子)
    double seedsAvgAll = 0.0;//选中区域中全部种子灰度的总和 (与全部种子数一起计算均值)
    //邻域(四邻域或八邻域)
    vector<vector<int>> neighborhood = {{0,-1},{0,1},{-1,0},{1,0},{-1,-1},{-1,1},{1,-1},{1,1}};
    //迭代计算区域
    while (!eachRound.empty())
    {
        int x = eachRound.front()[0];
        int y = eachRound.front()[1]; 
        eachRound.pop();
        //开始设置为状态值来表示该种子从哪个方向来，以不重新添加
        //四邻域可以计算，八邻域不方便；而且利用模板也可以达到目的，便去掉状态码了
        //int state = eachRound.front()[2];

        //中心种子点 第一个准则是直接用该点的灰度作为标准 -1.0越界下一步循环
        //center_avg = getPixelAvg(x, y);
        //if(center_avg == -1.0) continue;
        //qDebug()<<center_avg;

        //后续采取第二种准则，采取全部种子的灰度均值作为标准
        for (int i = 0; i<fourOrEight; i++) {
            int thisX = x + neighborhood[i][0];
            int thisY = y + neighborhood[i][1];

            double thisAvg = getPixelAvg(thisX, thisY);
            if((thisAvg != -1.0)&&(pixelState[thisX][thisY] == 0)&&(abs(center_avg-thisAvg) < threshold)){
                nextRound.push({thisX, thisY});
                m_RegionGet.push({thisX, thisY});
                pixelState[thisX][thisY] = 1;
            }
        }

        if((i>1200)||(nextRound.empty())){
            //达到循环次数 或没有新的种子停止
            qDebug()<<"cycle stop!::for num i::"<<i;
            break;
        }

        if(eachRound.empty())
        {   //一轮循环结束 开始下一轮  新一轮种子点替换
            eachRound = nextRound;
            //计算全部种子区域的灰度均值  加上最开始的那一个种子
            while(!nextRound.empty())
            {
                seedsNums++;
                seedsAvgAll = seedsAvgAll + getPixelAvg(nextRound.front()[0], nextRound.front()[1]);
                nextRound.pop();
            }
            center_avg = (seedsAvgAll + getPixelAvg(m_Seeds[0], m_Seeds[1])) / (seedsNums + 1);
            i++;    
        }      
    }
}

vector<double> ImgDivision::getImgComplexity()
{
    //利用灰度级，getGrayLevel()
    double N = m_Img->height() * m_Img->width();
    //IC 衡量从图像中获取感兴趣目标的复杂程度
    double IC = 0.0;
    for (int i = 0; i<256; i++) {
        if(m_GrayLevel[i] > 0) IC = IC - m_GrayLevel[i] * log(double(m_GrayLevel[i]) / N);
    }
    //Ent信息熵 图像中出现某种特征的几率 图像越复杂值越大
    double Ent = IC / N;
    //灰度共生矩阵 Gray Level Co-occurrence Matrix，GLCM
    //利用灰度空间相关的特征性质对图像中的纹理进行一定描述的方法
    //能量（E）、对比度（Con，用 CCon 表示）、相关度（Cov，用 CCov 表示）
    //权重系数分别设置为 1、1、-1、-1
    //qDebug()<<N<<" "<<IC<<" "<<Ent;
    return {IC, Ent};
}

vector<vector<double>> ImgDivision::getGLCM(int angle)
{
    //初始化灰度共生矩阵大小及值
    vector<vector<double>> glcm;
    glcm.resize(256);
    for (int i = 0; i < glcm.size(); i++) {
        glcm[i].resize(256);
    }
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            glcm[i][j] = 0;
        }
    }
    //计算各方向的共生矩阵
    vector<int> val = {0,0,0,0};
    switch (angle)
    {
        case 0:
            val = {0,0,0,-1,1,0};
            break;
        case 45:
            val = {1,0,0,-1,1,-1};
            break;
        case 90:
            val = {1,0,0,0,0,-1};
            break;
        case 135:
            val = {1,0,1,0,-1,-1};
            break;
        case 180:
            val = {0,0,1,0,-1,0};
            break;
        default:
            break;
    }
    for (int y = val[0]; y < m_Img->height()+val[1]; y++) {
        for (int x = val[2]; x < m_Img->width()+val[3]; x++) {
            QRgb pix1 = m_Img->pixel(x, y);
            int pix11 = int((qRed(pix1) + qGreen(pix1) + qBlue(pix1))/3.0);
            QRgb pix2 = m_Img->pixel(x+val[4], y+val[5]);
            int pix22 = int((qRed(pix2) + qGreen(pix2) + qBlue(pix2))/3.0);
            glcm[pix11][pix22] = glcm[pix11][pix22] + 1;
        }
    }

    return glcm;
}

vector<double> ImgDivision::getGLCMfeatures(int angle)
{
    vector<vector<double>> glcm = getGLCM(angle);
    //计算最大最小值
    int maxVal = 0, minVal = 0;
    for (int y = 0; y<glcm.size(); y++) {
        int thisMaxVal = *max_element(glcm[y].begin(), glcm[y].end());
        int thisMinVal = *min_element(glcm[y].begin(), glcm[y].end());
        if(maxVal < thisMaxVal) maxVal = thisMaxVal;
        if(minVal > thisMinVal) minVal = thisMinVal;
    }
    //共生矩阵归一化
    vector<vector<double>> glcmNorm = glcm;
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            glcmNorm[i][j] = double(glcm[i][j] - minVal) / double(maxVal - minVal);
        }
    }
    //对比度
    double Con = 0.0;
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            Con = Con + (i-j)*(i-j)*glcmNorm[i][j];
        }
    }
    //能量
    double Asm = 0.0;
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            Asm = Asm + glcmNorm[i][j]*glcmNorm[i][j];
        }
    }
    //相关度
    double Cov = 0.0;
    //均值计算
    double u1 = 0.0, u2 = 0.0;
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            u1 = u1 + i * glcmNorm[i][j];
        }
    }
    for(int j = 0; j<256; j++){
        for (int i=0; i<256; i++) {
            u2 = u2 + j * glcmNorm[i][j];
        }
    }
    //方差计算
    double d12 = 0.0, d22 = 0.0;
    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            d12 = d12 + (i-u1) * (i-u1) * glcmNorm[i][j];
        }
    }
    for(int j = 0; j<256; j++){
        for (int i=0; i<256; i++) {
            d22 = d22 + (j-u2) * (j-u2) * glcmNorm[i][j];
        }
    }

    for(int i = 0; i<256; i++){
        for (int j=0; j<256; j++) {
            Cov = Cov + (i * j * glcmNorm[i][j]*glcmNorm[i][j] - u1 * u2) / (d12*d22);
        }
    }

    return {Con, Asm, Cov};
}

double getLabFunc(double x)
{
    if(x>pow(6.0/29.0, 3.0)) return powl(x, 1.0/3.0);
    return 1.0/3.0 * pow(29.0/6.0, 2.0) * x + 4.0/29.0;
}

vector<vector<vector<double>>> ImgDivision::getLab()
{
    //xyz空间的大小初始化
    vector<vector<vector<double>>> xyz;
    xyz.resize(m_Img->height());
    for (int i = 0; i < xyz.size(); i++) {
        xyz[i].resize(m_Img->width());
    }
    for(int y = 0; y<m_Img->height(); y++)
    {
        for(int x = 0; x<m_Img->width(); x++)
        {
           xyz[y][x].resize(3);
        }
    }
    //rgb转xyz空间
    for(int y = 0; y<m_Img->height(); y++)
    {
        for(int x = 0; x<m_Img->width(); x++)
        {
            QRgb pix = m_Img->pixel(x, y);
            xyz[y][x][0] = 0.412453*qRed(pix) + 0.357580*qGreen(pix) + 0.180423*qBlue(pix);
            xyz[y][x][1] = 0.212671*qRed(pix) + 0.715160*qGreen(pix) + 0.072169*qBlue(pix);
            xyz[y][x][2] = 0.019334*qRed(pix) + 0.119193*qGreen(pix) + 0.950227*qBlue(pix);
        }
    }
    //Lab空间初始化
    vector<vector<vector<double>>> lab;
    lab.resize(m_Img->height());
    for (int i = 0; i < lab.size(); i++) {
        lab[i].resize(m_Img->width());
    }
    for(int y = 0; y<m_Img->height(); y++)
    {
        for(int x = 0; x<m_Img->width(); x++)
        {
           lab[y][x].resize(3);
        }
    }

    //xyz转lab
    for(int y = 0; y<m_Img->height(); y++)
    {
        for(int x = 0; x<m_Img->width(); x++)
        {
            QRgb pix = m_Img->pixel(x, y);
            lab[y][x][0] = 116.0 * getLabFunc(xyz[y][x][1] / 1.0) - 16.0;
            lab[y][x][1] = 500.0 * (getLabFunc(xyz[y][x][0] / 0.950456) - getLabFunc(xyz[y][x][1] / 1.0));
            lab[y][x][2] = 200.0 * (getLabFunc(xyz[y][x][1] / 1.0) - getLabFunc(xyz[y][x][2] / 1.088754));
        }
    }
    return lab;
}

double ImgDivision::getDistance(QPoint p1, QPoint p2, vector<vector<vector<double>>> lab, double P, double m)
{
    //空间距离
    double ds = sqrt( pow(double(p1.x() - p2.x()), 2.0) + pow(double(p1.y() - p2.y()), 2.0));
    //颜色距离
    double dc = sqrt( pow(double(lab[p1.y()][p1.x()][0] - lab[p2.y()][p2.x()][0]), 2.0)
                      + pow(double(lab[p1.y()][p1.x()][1] - lab[p2.y()][p2.x()][1]), 2.0)
                      + pow(double(lab[p1.y()][p1.x()][2] - lab[p2.y()][p2.x()][2]), 2.0));

    return sqrt( dc + ds*ds / P * m * m);
}

/*
void ImgDivision::getRegionGrowRes(double threshold)
{
    m_RegionGet.push({m_Seeds[0], m_Seeds[1]});

    queue<vector<int>> eachRound;//每一循环存储的新种子
    queue<vector<int>> nextRound;//每一循环存储的新种子
    eachRound.push(m_Seeds);

    int i = 0;
    while (!eachRound.empty()) {
        int x = eachRound.front()[0];
        int y = eachRound.front()[1];
        int state = eachRound.front()[2];
        eachRound.pop();

        //中心种子点
        double center_avg = getPixelAvg(x, y);
        if(center_avg == -1.0) continue;
        //up向上处点
        double up_avg = getPixelAvg(x, y-1);
        if((up_avg != -1.0)&&(state != 11)&&(isAddVal(x, y-1))&&(abs(center_avg-up_avg) < threshold)){
            nextRound.push({x, y-1, 22});
            //m_RegionGet.push({x, y-1});
        }
        //down 向下点
        double down_avg = getPixelAvg(x, y+1);
        if((down_avg != -1.0)&&(state != 22)&&(isAddVal(x, y+1))&&(abs(center_avg-down_avg) < threshold)){
            nextRound.push({x, y+1, 11});
            //m_RegionGet.push({x, y+1});
        }
        //左边点
        double left_avg = getPixelAvg(x-1, y);
        if((left_avg != -1.0)&&(state != 33)&&(isAddVal(x-1, y))&&(abs(center_avg-left_avg) < threshold)){
            nextRound.push({x-1, y, 44});
            //m_RegionGet.push({x-1, y});
        }
        //右边点
        double right_avg = getPixelAvg(x+1, y);
        if((right_avg != -1.0)&&(state != 44)&&(isAddVal(x+1, y))&&(abs(center_avg-right_avg) < threshold)){
            nextRound.push({x+1, y, 33});
            //m_RegionGet.push({x+1, y});
        }

        if(eachRound.empty()) {
            eachRound = nextRound;
            while(!nextRound.empty()){
                nextRound.pop();
            }
        }

        i++;
        if(i>3600000){
            m_RegionGet = eachRound;
            break;}

    }
    qDebug()<<i;
}
*/

/*
bool ImgDivision::isAddVal(int x, int y)
{
    //判断是否重复 采取遍历队列 很慢
    queue<vector<int>> newRegionGet = m_RegionGet;
    while(!newRegionGet.empty())
    {
        int xx = newRegionGet.front()[0];
        int yy = newRegionGet.front()[1];
        newRegionGet.pop();
        if((x==xx)&&(y==yy)) return false;
    }
    return true;
}
*/
